Understanding COM Objects

By Shredplayer

 

Contents

 

  Introduction

  What is COM?

  Why use COM?

  What Is a Type Library?

  Data types

  Signed and Unsigned Integers

  The IUnknown and IDispatch Interfaces

  Calling a Method With No Arguments

  Getting and Setting properties

  Passing and Omitting optional arguments to methods

  Using $comval()

  Using Exposed Objects and Properties from Installed Programs

  ProgID’s (Programmatic Identifiers)

  Exposing Methods and Properties

  Windows Management Instrumentation (WMI)

  InstancesOf Method

  WMI Query Language (WQL)

  ExecQuery Method

  Passing Methods to $comval

  WQL OPERATORS and KEYWORDS

  Connecting to root\default namespace

  Improving Performance

  Browsing the CIM Schema

 

Introduction

  In this tutorial you will learn how to take advantage of COM(Component Object Model) via scripts.

  our purpose here is to use existing COM objects within the Operating System or COM objects from installed

  software that we can use to enhance Scripts.

 

What is COM?

  COM is a binary standard for software object interaction. This allows any two components to communicate

  regardless of what machine or operating systems , as long as it supports COM and it also doesn’t matter

  what language the components are written in, C++,Visual Basic etc.

 

  COM objects are well encapsulated. You cannot gain access to the internal implementation of the object;

  you have no way of knowing what data structures the object might be using. But can we Communicate?

  the answer is YES through the Interface(IDispatch and IUnknown), it’s the only way to access COM objects.

 

Why use COM?

  Simply because you can create identifiers for your scripts which isn’t built-in to mIRC or it offers added

  functionality than the built-in identifier.

 

  Below are usage and syntax:

 

  /comopen name Progid

  This opens a COM connection to object progid ie. Excel.Application, and assigns the connection a name.

  Name – can be anything you want.

  Progid – (Programmatic Identifier) Excel.Application.

  Excel - Type Library

  Application - Object

 

What Is a Type Library?

 

  A type library is a file or part of a file that describes the type of one or more objects. Type libraries do not

  store objects they store type information.

 

  /comclose name

  This closes the specified COM connection.

 

  /comreg -u filename

  This registers/unregisters a COM DLL with windows.

 

  $comerr

  This should be checked after a call to any COM command or identifier. Returns 1 if there was an error, 0 otherwise.

  comopen name progid

  if ($comerr) { command }

 

  $com(name,member,method,type1,value1,...,typeN,valueN)

  This calls a member of an open COM connection with the specified methods and parameters.

 

  name   - connection name.

 

  member - member name.

 

  methods - Combination of the following values added together:

 

Methods

Value

Description

DISPATCH_METHOD

1

Executes or Invokes a method.

DISPATCH_PROPERTYGET

2

Gets a property.

DISPATCH_PROPERTYPUT

4

Sets a property .

DISPATCH_PROPERTYPUTREF

8

Sets a property by a reference assignment

rather than a value assignment. This is valid

only when the property accepts a reference

to an object.

 

  The only thing that differs Scripting Languages from one another is Syntax but implementation may differ,

  it’s functionality is still the same.

 

  [JScript]

 

  function DeleteFile(filespec)

  {

     var fso;

     fso = new ActiveXObject("Scripting.FileSystemObject");

     fso.DeleteFile(filespec);

  }

 

  [VBScript]

 

  Sub DeleteFile(filespec)

     Dim fso

     Set fso = CreateObject("Scripting.FileSystemObject")

     fso.DeleteFile(filespec)

  End Sub

 

  [mIRC]

 

  fso {

     comopen fso Scripting.FileSystemObject

     var %fso = $com(fso,DeleteFile,1,string,filespec)

     comclose fso

  }

 

  Unlike programming languages, scripting languages including mSL(mIRC Scripting Language)

  (wow I like the sound of that) do not force you to specify a return data type because variables are

  automatically cast to the appropriate data type, VBScript on the other hand uses the same data type

  for variables, Variant.

 

Data Types

  The characteristic of a variable that determines what kind of data it can hold.

 

Type

Description

i1

1-byte signed integer. see Issues

i2

2-byte signed integer (-32768 to 32767).

i4

4-byte signed integer ( -2147483648 to 2147483647).

ui1

1-byte unsigned integer  (0 to 255).

ui2

2-byte unsigned integer (0 to 65535).

ui4

4-byte unsigned integer (0 to 4294967295).

int

Integer (-2147483648 to 2147483647).

uint

Unsigned integer (0 to 4294967295).

r4

Real, 4-byte floating point number (1.17549435E-38 to 3.40282347E+38).

r8

Double real, 8-byte floating point number  (2.2250738585072014E-308 - 1.7976931348623157E+308).

cy

A currency number stored as an 8-byte (-922337203685477.5625

to 922337203685477.5625).

date

Contains date and time, stored as an 8-byte floating-point number.

decimal

This data type indicates numeric data with a fixed precision and scale.

0 through +/-79,228,162,514,264,337,593,543,950,335 with no decimal point;
0 through +/-7.9228162514264337593543950335 with 28 places to the

right of the decimal; smallest nonzero number is
+/-0.0000000000000000000000000001 (+/-1E-28).

bool

Can contain any string or numeric representation. see Boolean

bstr

Basic string , This data type indicates a null-terminated

Unicode character string.

variant

Can contain string, date, time, Boolean, or numeric values.

dispatch

This data type indicates a pointer to an IDispatch interface.

unknown

This data type indicates a pointer to an IUnknown interface.

error

This data type indicates a 32-bit error code.

 

legend: I = integer , R = real , U = unsigned

 

Some issues regarding the range of variable types.

 

Signed i1 as far as i know ranges to -128 to 127, since this is a signed integer it must handle

an optional sign but testing shows it cannot handle (-) sign and the range is the same as

the unsigned ui1 (0 to 255). since this hasn't been resolve yet so i1 will only handle integers

ranging from 0 to 255.

 

the sample below can test how much data a variable can handle.

syntax: $datatest(variable type,value)

 

 datatest {

  ; we'll use Shell.Application for reference only.
     comopen c Shell.Application

  ; since this is only for reference we omits the member value and assigns the variable a name.
     var %i = $com(c, , 1,$1 var, $2)
     %i = $com(c,var)
     return %i
  }

 

Note: This was tested on mIRC 6.16

 

BSTR and Strings

 

  Strings - A data type consisting of a sequence of contiguous characters that represent the characters

  themselves rather than their numeric values.

 

  BSTR - a pointer to a null-terminated Unicode character array that is preceded by a 4-byte length field.

 

  Technically BSTR and Strings are not the same(as far as VB is concern), BSTR is a pointer to the unicode

  character array while Strings are unicode character arrays. This can be confusing but that doesn’t concern us

  much since both will work, it's now depends on what you want to use.

 

  Boolean -  can be any valid string or numerical value.

 

   Numeric representation - FALSE = 0 and TRUE != 0

      $com(name,member,method,bool,0) is FALSE

      $com(name,member,method,bool,-1) is TRUE

 

   String representation - TRUE = TRUE and FALSE != TRUE

      $com(name,member,method,bool,TRUE) is TRUE

      $com(name,member,method,bool, ANY NON TRUE STRING) is FALSE

 

Note: Every programming & scripting languages have different numerical representation of boolean.

   though this isn't a big issue as a personal advice you should restrict usage of boolean variables to

   the logical values (TRUE & FALSE) and not rely on equivalent numeric values.

 

Signed and Unsigned Integers
all integer types come in two varieties, signed and unsigned.

Signed integers are either negative or positive and Unsigned integers are always positive.
 

  Signed :  128 , -127, -256

 

  Unsigned : 1, 255, 65535

 

  $com(name/N,varname)

  Returns value of the specified variable name.

 

  $comcall(name,alias,...)

 

  $comcall() uses the same format as $com() apart from the alias. It is multi-threaded so it will not halt the script and

  will call the specified alias once the call returns.

 

  $comval(name,N,member)

  Returns member value for the Nth instantiation of the enumerated collection in name.

 

  $com(name/N)

  Returns name if connection is open, or name of Nth connection. N = 0 returns number of open connections.

 

  Properties: progid, dispatch, unknown, result, error, errortext, argerr

 

  progid - object name.

 

  dispatch – boolean value when dispatch pointer exists.

 

  unknown – boolean value when unknown pointer exists.

 

  result - the value returned by the COM object member after the call.

  

  argerr - Nth position of the argument that caused the error, if the error was due to an invalid variable type,

  arguments are stored in an array and in reverse order, so the first argument is the one with the highest

  index in the array.

  ex:

        This syntax has 3 arguments $com(name,member,method,[arg1] [arg2] [arg3]) if you supplied invalid

        arguments on arg1 its argerr value will be 3 $com(name,member,method,[argerr3] [argerr2] [argerr1])

              using argerr can pinpoint which arguments supplied is invalid.

 

  error  - error value, if there was an error.

 

  errortext - error description associated with error.

 

Errortext

Description

DISP_E_MEMBERNOTFOUND

The requested member does not exist, or the call to Invoke

tried to set the value of a read-only property.

 

DISP_E_TYPEMISMATCH

One or more of the parameters could not be coerced.

DISP_E_UNKNOWNNAME

One or more of the given names were not known.

DISP_E_EXCEPTION

The application needs to raise an exception.

DISP_E_BADPARAMCOUNT

The number of elements provided is different from the number

of parameters accepted by the method or property.

DISP_E_PARAMNOTOPTIONAL

Parameter not optional.

DISP_E_NOTACOLLECTION

Does not support a collection.

DISP_E_BADVARTYPE One of the parameters  is not a valid variant type.
DISP_E_NONAMEDARGS Does not support named arguments.
DISP_E_OVERFLOW One of the parameters could not be coerced to the specified type.

DISP_E_PARAMNOTFOUND

Correct number of parameters was pass but one or more parameters

was incorrect.

DISP_E_UNKNOWNLCID

The member being invoked interprets string parameters according to

the LCID, and the LCID is not recognized.

DISP_E_UNKNOWNINTERFACE

The interface identifier passed in riid is not IID_NULL.

 

 

Optional and Non-Optional Arguments

 

  Optional – Indicates that an argument is not required and can be omitted.

 

  Non Optional – argument required by the procedure, omitting will result failure of Com call.

 

Positional and Named Arguments

 

  Positional Arguments – the supplied arguments must be in order.

                              VB ex: foo(strName,intAge)

                                        $com(name,member,method,bstr,nick,int,19)

 

  Named Arguments – the supplied arguments can be in any order  provided that you pass an argument name followed by

                                  a colon and an equal sign (:=), followed by the argument value.

                                     ex: foo(strName,intAge)

                                          $com(name,member,method,int,intAge:=19,bstr,strName:=nick)

                                          or

      $com(name,member,method,intAge:=19,bstrName:=nick)

                                          this is not implemented in mIRC, im just showing you how it might look like.

 

 

The IUnknown and IDispatch Interfaces

 

  IUnknown interface lets clients get pointers to other interfaces on a given object.

 

  IDispatch interface exposes objects, methods and properties.

 

      a GetFile method that returns a File object corresponding to the file in a specified path.

Attributes property determines whether the attributes are read-only, system , etc..

 

Calling a Method With No Arguments

  When calling a method with no arguments you only need to pass the connection name, member name

  and the DISPATCH_METHOD value and because this does not take any arguments it does not return

  any result, hence $com(name).result is not needed; See the example below.

 

  Example:

 

  CascadeWindows {

     comopen Cascade Shell.Application

 

  ; Cascade – Name

  ; Shell – Type Library

  ; Application – Object

 

  ; this echoes and will halt the process if connection has failed.

     if ($comerr) { echo comopen failed | halt }

 

  ; DISPATCH_METHOD (1) invokes the method.

     echo Com: $com(Cascade,CascadeWindows,1)

     comclose Cascade

  }

 

Getting and Setting Properties

  Properties are accessed by passing property name and adding DISPATCH_PROPERTYGET or

  DISPATCH_PROPERTYPUT values to DISPATCH_METHOD.

 

  Every DISPATCH_PROPERTYPUT must define at least one argument.

 

  Example:

 

  Ie {

     comopen ie InternetExplorer.Application

     if ($comerr) { echo comopen failed | halt }

 

  ; Getting a property.

  ; add DISPATCH_METHOD value to DISPATCH_PROPERTYGET.

  ; 1 + 2 = 3

     echo Com: $com(ie,FullName,3)

     echo Result: $com(ie).result

 

  ; Setting a property.

  ; add DISPATCH_METHOD value to DISPATCH_PROPERTYPUT.

  ; 1 + 4 = 5

  ; this will remove the StatusBar(0 = visible, 1 = Hidden)

     echo Com: $com(ie,StatusBar,5,i1,0)

  ; sets Visible property

     echo Com: $com(ie,Visible,5,i1,1)

     comclose ie

  }

 

Passing and Omitting Optional Arguments to Methods

  You can pass only those arguments that you really need and omit some of the optional arguments

 

  Example:

 

  Popup(Text As String, [SecondsToWait], [Title], [Type])

 

  Notice that the only required argument is the Text and the rest are optional.

     $com(name,Popup,3,string,Title)

     $com(name,Popup,3,string,Title,i4,0,string,mIRC,i4,2)

  but what if you want to omit [SecondsToWait] and pass the remaining arguments?

  You just can’t use $com(name,Popup,3,string,Title,string,mIRC,i4,2) it will raise an error.

 

  In automation usually we pass VT_ERROR as the type of the omitted arguments, with the status

  code DISP_E_PARAMNOTFOUND(-2147352572) as the value, this error is listed in Winerror.h

 

  -2147352572 run-time error code can be retrieved by assigning a name to error variable.

     $com(name,member,method,error varname, ,......)

  and using $com(name,varname) to return the error code.

 

  In mIRC, what we can do is to pass error data type and leave the parameter empty and the call

  will use the default value declared for that argument, but remember this is only valid for optional arguments.

 

  Popup {

     comopen popup Wscript.Shell

     if ($comerr) { echo comopen failed | halt }

     echo Com: $com(popup,Popup,3,string,Passing and Omitting arguments,i4,0, error, ,i4,2)

     echo Result: $com(popup).result

     comclose popup

  }

 

  Example:

 

     BrowseForFolder(Hwnd As Long, Title As String, Options As Long, [RootFolder])

 

  When the optional arguments [RootFolder] is the last parameter to pass,

  We don’t need to pass like this;

     $com(name,BrowseForFolder,3,i4,0,string,Title,i4,Options,error, )

  All we need is omit the argument;

     $com(name,BrowseForFolder,3,i4,0,string,Title,i4,Options)

 

  Hwnd – can be $window(@).hwnd or $dialog(name).hwnd or 0

  Text - Text

  Options – integer value eg. 512 (removes No New folder button)

  Dir – Directory can also be any integer value of Special Folder Constants.

          Just replace the string type to i4.

 

  //echo $BrowseForFolder(0,Select Folder,512,$mircdir) – passes all arguments.

  //echo $BrowseForFolder(0,Select Folder,512) – omits last argument.

 

 

  BrowseForFolder {

     comopen BFF Shell.Application

     if ($comerr) { echo comopen failed | halt }

     echo Com: $com(BFF,BrowseForFolder,3,i4,$1,string,$2,i4,$3,string,$4,dispatch* Items)

     echo Result: $com(BFF).result

     comclose BFF

      if $com(Items) {

     echo Com: $com(Items,Items,3,dispatch* Item)

     echo Result: $com(Items).result

     comclose Items

  }

    if $com(Item) {

     echo Com: $com(Item,Item,3,dispatch* Path)

     echo Result: $com(Item).result

     comclose Item

  }

     if $com(Path) {

     echo Com  $com(Path,Path,3)

     echo Path: $com(Path).result

     comclose Path

    }

  }

 

  Note: error checking not included in the above code.

    Other Properties are available for error checking like IsFileSytem to check if the selected

    Folder is a file system folder.

 

Using $comval(name,N,member)

  $comval() returns the member value for the Nth Instantiation of the enumerated

  collection of instances.

 

  Example:

 

  This will enumerate collection of drives.

 

  EnumDrives {
     comopen drives Scripting.FileSystemObject

     if ($comerr) { echo comopen failed | halt }
     echo Com: $com(drives,Drives,3,dispatch* items)
     echo Result: $com(drives).result
     comclose drives
     if $com(items) {

 

  ; count the number of drives.
     echo Com: $com(items,Count,3)
     var %c = $com(items).result,%i = 1

 

  ; loop the result.
     while (%i <= %c) {

  ; we pass the Path Property.
     echo Drive: $comval(items,%i,Path)

  ; Other Properties: AvailableSpace, DriveLetter, DriveType, FileSystem, IsReady, RootFolder

  ; SerialNumber, ShareName, TotalSize, VolumeName.


     inc %i
    }
     comclose items
    }
  }

 

Using Exposed Objects and Properties from Installed Programs

  This example takes advantage of NERO exposed Objects and Properties, you can burn

  Audio CD’s , Image, VCD, etc. basically all of capabilities of the Program can be use.

  This of course if Nero is Installed.

 

  Example:

 

  This will Eject then Load CD-ROM Drives.

  Nero {
     comopen Nero Nero.Nero
     if ($comerr) { echo comopen failed | halt }
     echo Com $com(Nero,GetDrives,1,i1,0,dispatch* Drive)
     echo Com $com(Nero).result
     comclose nero
     if $com(Drive) {
     echo Com $com(Drive,Count,3)
     var %c = $com(Drive).result, %i = 1
     while (%i <= %c) {
     echo Com: $comval(Drive,%i,EjectCD)
     echo Com: $comval(Drive,%i,LoadCD)
     inc %i
    }
     comclose Drive
   }
  }

 

ProgID’s (Programmatic Identifiers)

  ProgID’s are registered on your system registry, The format of a ProgID is <Program>.<Component>.<Version>

  separated by periods and with no spaces, as in Word.Document.6, basically we don’t need to specify version

  rather we use the version independent ProgID.

 

  By convention, the ProgID is named <Type Library>.<Object>

 

Steps in finding ProgID’s.

1.  Run Regedit

2.  Press CTRL+F

3.  Enter the word ProgID or VersionIndependentProgID then click Find Next

4.  Once a ProgID is found, see if it complies with our ProgID format and you can also test it in mIRC with

 /comopen name <ProgID.YouFound> to see if mIRC can open it.

5.  Optional. Find the InprocServer32 key nested along the ProgID key and write down it’s associated dll

      path for later reference.

6.  To keep on finding ProgID’s Press F3

 

  If you’re too lazy to do this check out the ProgiDEnumerator example in the WMI Section.

 

Exposing Methods and Properties

  Methods and Properties can be exposed using Visual Basic Object Browser or if Word and Excel is installed, look

  under Tools\Macro\Visual Basic Editor (may differ from versions) or Press ALT+F11 then Press F2 to open

  Object Browser, under Tools\References select type libraries of your choice or you can browse the Inprocserver32

  path that you found then add it to our references, this will automatically added to the Object Browser. Select the

  added type library and Object Methods,Properties and syntax will be exposed.

 

  Object Browser

  The Object Browser provides information about the classes, methods, and properties a COM object exposes.

 

  OLE-COM OBJECT VIEWER can also be use if Visual C++\Studio is installed.

 

Windows Management Instrumentation (WMI)

  WMI can be use to manage computer hardware, computer software, and nearly everything in between,

  mIRC version 6.16 added $comval() it main task is to return a value of Nth collection of instances.

 

Get Method

  The Get method of the SWbemServices object retrieves an object, either a class definition or an instance,

  based on the object path.

 

  Example:

 

  Win32_Processor

 

  CPU {

     comopen Locator WbemScripting.SWbemLocator

     if ($comerr) { echo comopen failed | halt }

     echo Com: $com(Locator, ConnectServer, 3, dispatch* Services)

     echo Result: $com(Locator).result

     comclose Locator

     if $com(Services) {

  ; Win32_Processor.DeviceID="CPU0" is an Instance of Win32_Processor

     echo Com: $com(Services, Get, 3,string, Win32_Processor.DeviceID="CPU0",dispatch* Item)

     echo Result: $com(Services).result

     comclose Services

  }

     if $com(Item) {

     echo Com: $com(Item,Caption,3)

     echo Caption: $com(Item).result

     echo Com: $com(Item,Manufacturer,3)

     echo Manufacturer: $com(Item).result

   ; GetObjectText_ can be used to get Object contents or Properties in MOF syntax.

    echo GetObjectText_: $com(Item,GetObjectText_,3)

    write –c MOF.txt $com(Item).result

    run MOF.txt

    comclose Item

    }

  }

 

GetObjectText_

  This returns a textual rendering of the object, and can be used to display an object's contents.

  The output format is MOF(Managed Object Format) syntax.

 

  Note: line too long error will be encountered if MOF contents exceed mIRC variable limits.

 

Getting and Setting Properties

  Properties are accessed the same way as we usually accessed a property by passing a property name

  and adding the value of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT to DISPATCH_METHOD,

  the only thing differs is that we need to use Put_ method to update the changes.

 

Put_ Method

  The Put_ method creates or updates an instance or class object to WMI

  You can use this method after you modify any properties or methods and

  your changes are written to WMI.

 

  The example below demonstrates that task.

 

  Example:

 

  Win32_LogicalDisk

 

  RenameDisk {
     comopen Locator WbemScripting.SWbemLocator
     if ($comerr) halt
     echo Com: $com(Locator, ConnectServer, 3, dispatch* Services)
     echo Result: $com(Locator).result
     comclose Locator
     if $com(Services) {
     echo Com: $com(Services, Get, 3,string*,Win32_LogicalDisk.DeviceID="C:",dispatch* Item)
     echo Result: $com(Services).result
     comclose Services
     }
     if $com(Item) {

  ; gets the VolumeName Property.
     echo Com: $com(Item,VolumeName,3)
     echo 3 Disk Name: $com(Item).result

  ; set the VolumeName property to "My Disk Name"
     echo Com: $com(Item,VolumeName,5,string,My Disk name)

  ; updates the changes made by using Put_ method.
     echo Com: $com(Item,Put_,3)

  ; gets the new name.
     echo Com: $com(Item,VolumeName,3)
     echo New name: $com(Item).result
     comclose Item
   }
  }

 

  (*) the asterisk is use to make a variable by reference, this means that mIRC will not create

  a new variable and this is helpful in preventing some COM related crashes.

 

  Note: you cannot set to a read-only property.

 

InstancesOf Method

  The InstancesOf method of the SWbemServices object creates an enumerator that returns

  the instances of a specified class. The good thing about this is you don’t have to supply

  an object path, all we pass is the class name eg. Win32_Service

  

  Example:

 

  Win32_Service

 

  Service {

     comopen Locator WbemScripting.SWbemLocator

     if ($comerr) { echo comopen failed | halt }

     echo Com: $com(Locator,ConnectServer,3, dispatch* Services)

     echo Result: $com(Locator).result

     comclose Locator

     if $com(Services) {

     echo com: $com(Services, InstancesOf,3,string,Win32_Service,dispatch* Instances)

     echo result: $com(Services).result

     comclose Services

  }

     if $com(Instances) {

     echo com: $com(Instances,Count,3)

     var %c = $com(Instances).result, %i = 1

     while (%i <= %c) {

     echo Service: $comval(Instances,%i, DisplayName)

     echo State: $comval(Instances,%i, State)

     inc %i

  }

      comclose instances

    }

  }

 

WMI Query Language (WQL)

WQL is a subset of the ANSI standard Structured Query Language (SQL).

 

if you're into SQL query you'll be feel at home using WQL since WMI borrowed the technique

from database style query.

 

simple WQL Query that retrieves all Logical drives

format: SELECT PROPERTIES FROM CLASS

     SELECT * FROM Win32_LogicalDisk

 

using WHERE clause to retrieve logical drives with NTFS filesystem.

  format: WHERE <property> <operator> <constant>

            or

               WHERE <constant> <operator> <property>

     SELECT * FROM Win32_LogicalDisk WHERE FileSystem = "NTFS"

 or

     SELECT * FROM Win32_LogicalDisk WHERE "NTFS" = FileSystem

 

   If a subset of properties is only needed replace the asterisk with desired Properties.

   In this way it will only query the property and reduce memory bandwith usage,

   and the only accessible property from $comval is the property supplied.

     SELECT FileSystem FROM Win32_LogicalDisk WHERE FileSystem = "NTFS"

 

 Note: the query string is not case sensitive.

 

ExecQuery Method

  The ExecQuery method of the SWbemServices object executes a query to retrieve objects.

 

  Example:

 

  This uses ExecQuery where it will only returns the specified Query unlike InstancesOf where it returns all

  Instances . The below example only returns disk with NTFS file system.

   

  QueryDisk {

     comopen Locator WbemScripting.SWbemLocator

     if ($comerr) { echo comopen failed | halt }

     echo Com: $com(Locator,ConnectServer,3, dispatch* Services)

     echo Result: $com(Locator).result

     comclose Locator

     if $com(Services) {

     echo com: $com(Services, ExecQuery,3,string,SELECT * FROM Win32_LogicalDisk WHERE FileSystem = "NTFS" ,dispatch* Instances)

     echo result: $com(Services).result

     comclose Services

  }

    if $com(Instances) {

    echo com: $com(Instances,Count,3)

    var %c = $com(Instances).result, %i = 1

    while (%i <= %c) {

    echo Com: $comval(Instances,%i, Name) is $comval(Instances,%i, FileSystem) FileSystem

    inc %i

   }

    comclose instances

    }

  }

  

Passing Methods to $comval

  methods can also be pass to $comval just like passing properties.

  property - $comval(name,N,property)

  method - $comval(name,N,method)

 

  below sample demonstrate the task.

 

  Win32_Printer

 

  Example:

 

  PrintTestPage {
     comopen Locator WbemScripting.SWbemLocator
     if ($comerr) { echo comopen failed | halt }
     echo Com: $com(Locator,ConnectServer,3, dispatch* Services)
     echo Result: $com(Locator).result
     comclose Locator
     if $com(Services) {

  ; this queries the Win32_Printer class and will only return the default printer.
     echo com: $com(Services, ExecQuery,3,string,SELECT * FROM Win32_Printer WHERE Default = TRUE,dispatch* Instances)
     echo result: $com(Services).result
     comclose Services
     }
     if $com(Instances) {

  ; echoes the Printer name using caption property.
     echo Default: $comval(Instances,1, Caption)

  ; Invokes the PrintTestPage method.
     echo PrintTestPage: $comval(Instances,1, PrintTestPage)

  ; return 0 - sucess or 5 - access denied.
     comclose instances
   }
  }

 

  Unfortunately $comval(name,N,Member) accepts only 3 parameters, it would great if

  it would be implemented like this;

 

  $comval(name,N,member,method,...,...)

 

  change the properties through $comval.

  eg. $comval(name,N,VolumeName,5,string,My New Volume Name)

 

Terminate Method

  Terminates a process and all of its threads.

 

  The below sample terminates all running process of "Notepad.exe".

 

  Example:

 

  EndProcess {
     comopen Locator WbemScripting.SWbemLocator
     if ($comerr) { echo comopen failed | halt }
     echo Com: $com(Locator,ConnectServer,3, dispatch* Services)
     echo Result: $com(Locator).result
     comclose Locator
     if $com(Services) {
     echo com: $com(Services, ExecQuery,3,string,SELECT Name FROM Win32_Process WHERE Name = "Notepad.exe",dispatch* Instances)
     echo result: $com(Services).result
     comclose Services
     }
     if $com(Instances) {
     echo Com: $com(Instances,Count,3)
     var %c = $com(Instances).result, %i = 1
     while (%i <= %c) {
     echo Process: $comval(Instances,%i, Terminate)
     inc %i
     }
     comclose instances
   }
  }

 

ProgID Enumerator

  If you’re too lazy finding ProgID on the registry this the thing for you, the Win32_ProgIDSpecification Class

  represent any programmatic identifier (ProgID) that needs to be registered during a given installation, this

  means that not all ProgID will be enumerated, well at least.

 

  Example:

 

  ProgIDEnumerator {

     comopen Locator WbemScripting.SWbemLocator

     if ($comerr) { echo comopen failed | halt }

     echo Com: $com(Locator,ConnectServer,3, dispatch* Services)

     echo Result: $com(Locator).result

     comclose Locator

     if $com(Services) {

  ;  LIKE "%.%" – it queries ProgID if contains (.)

     var %prop = ProgID, Description

     echo com: $com(Services, ExecQuery,3,string,SELECT %prop FROM Win32_ProgIDSpecification WHERE ProgID LIKE "%.%",dispatch*      Instances)

     echo result: $com(Services).result

     comclose Services

  }

     if $com(Instances) {

     echo com: $com(Instances,Count,3)

     var %c = $com(Instances).result, %i = 1

     while (%i <= %c) {

     echo ProgID: $comval(Instances,%i, ProgID)

     echo Description: $comval(Instances,%i, Description)

     inc %i

  }

     comclose instances

    }

  }

 

 

WQL OPERATORS and KEYWORDS

 

Operators

Description

=

equal to

!= or <>

not equal to

<

less than

>

larger than

>=

larger than or equal to

<=

smaller than or equal to

 

SELECT - returns instances of the specified class and any of its subclasses

   SELECT * FROM CLASS

   SELECT * FROM Win32_LogicalDisk

 

  You can also Query desired property by replacing the * (asterisk)

  The only property queried will be available to $comval

     SELECT property FROM CLASS

     SELECT FileSystem FROM Win32_LogicalDisk

 

  Or using multiple properties

     SELECT property1, property2, property3 FROM CLASS

  But we just can’t use a string with comma(,) this because mIRC will treat it as arguments.

     SELECT FileSystem, FreeSpace, Name FROM Win32_LogicalDisk

 

  Using $chr(44) will do or set a variable.

    %var = FileSystem, FreeSpace, Name

    SELECT %var FROM Win32_LogicalDisk

 

WHERE - The WHERE clause is made up of a property or keyword, an operator, and a constant.

     SELECT * FROM CLASS WHERE <property> <operator> <constant>

     SELECT * FROM CLASS WHERE <constant> <operator> <property>

 

     SELECT * FROM Win32_LogicalDisk WHERE Name = "C:"

  or

     SELECT * FROM Win32_LogicalDisk WHERE "C:" = Name

 

OR - Combines two conditions.

  This will query if name is C: or D:

     SELECT * FROM Win32_LogicalDisk WHERE Name = "C:" OR Name = "D:"

 

AND

  Will query if FileSystem is equal to NTFS and Quota is disabled.

     SELECT * FROM Win32_LogicalDisk WHERE FileSystem = "NTFS" AND QuotasDisabled = TRUE

 

IS - Comparison operator used with NOT and NULL.

  Returns Instance if FileSystem IS NULL

     SELECT * FROM Win32_LogicalDisk WHERE FileSystem IS NULL

 

IS NOT

  Returns Instance if FileSystem IS NOT NULL.

     SELECT * FROM Win32_LogicalDisk WHERE FileSystem IS NOT NULL

  The IS and IS NOT operators are valid in the WHERE clause only if the constant is NULL.

 

LIKE - The LIKE operator determines whether or not a character string matches a specified pattern.

  [] - Any one character within the specified range ([a=f]) or set ([abcdef]).

  ^ - Any one character not within the range ([^a=f]) or set ([^abcdef].)

  % - Any string of 0 (zero) or more characters.

  _  -  Any one character. Any literal underscore used in the query string must be escaped

  by placing it inside [] (square brackets).

 

     SELECT * FROM Win32_LogicalDisk WHERE FileSystem LIKE "%NTFS%"

If the query includes _(underscore) enclosed it with [] escape characters because

  underscores are meta characters.

  In this example it queries if the VolumeName is like _Disk

     SELECT * FROM Win32_LogicalDisk WHERE VolumeName LIKE "%[_]Disk%"

  Multiple _(underscore)

     SELECT * FROM Win32_LogicalDisk WHERE VolumeName LIKE "%[_][_]Disk%"

 

Multiple Operators

     SELECT * FROM Win32_LogicalDisk WHERE (Name = "C:" OR Name = "D:")

          AND  FreeSpace > 10000000  AND   DriveType = 3

 

ASSOCIATORS OF - retrieves all instances that are associated with a particular source instance.

     ASSOCIATORS OF {ObjectPath}

     ASSOCIATORS OF {Win32_LogicalDisk.DeviceID="C:"}

  We can’t use { } so we set a variable.

     %var = {Win32_LogicalDisk.DeviceID="C:"}

     ASSOCIATORS OF %var

 

NULL - Indicates an object does not have an explicitly assigned value.

FALSE - Boolean operator.

TRUE - Boolean operator.

NOT - Comparison operator.

 

Connecting to root\default namespace

  So far all we tried is Providers located in root\cimv2 namespace which is the default namespace when arguments

  are omitted in the ConnectServer Method, don' be confused with the name root\default because in WMI scripting

  the default namespace is root\cimv2.

 

     ConnectServer([strServer As String = "."], [strNamespace As String], [strUser As String], [strPassword As String],

     [strLocale As String], [strAuthority As String], [iSecurityFlags As Long], [objWbemNamedValueSet As Object])

 

     $com(name,ConnectServer,3,dispatch* var)

  in this sample we omitted all optional arguments including strNamespace, this is ok but this will default to

  root\cimv2 namespace and most providers resides on this namespace but other providers like System restore

  resides at root\default and we just can't use those providers if we omits the namespace argument.

  so what we'll do is provide a namespace.

 

     $com(name,ConnectServer,3,string,<myServer>,string,root\default, dispatch* var)

  we pass server name to connect with the namespace specified, in this case root\default.

  or we omits the server name by passing error data type and leave the parameter empty.

     $com(name,ConnectServer,3,error, ,string, root\default ,dispatch* var)

 

  Below sample uses System Restore to enumerate restore points available.

 

  Example:

 

  RestorePoints {
     comopen Locator WbemScripting.SWbemLocator
     if ($comerr) { echo comopen failed | halt }

  ; connects to root\default Namespace.
     echo Com: $com(Locator,ConnectServer,3,error, ,string, root\default, dispatch* Services)
     echo Result: $com(Locator).result
     comclose Locator
     if $com(Services) {
     echo com: $com(Services, ExecQuery,3,string,SELECT Description FROM SystemRestore,dispatch* Instances)
     echo result: $com(Services).result
     comclose Services
     }
     if $com(Instances) {
     echo Com: $com(instances,Count,3)
     var %c = $com(instances).result,%i = 1
     while (%i <= %c) {
     echo Result: $comval(instances,%i, Description)
     inc %i
     }
     comclose instances
   }
  }

 

Improving Performance

  WMI queries tends to eat system resources specially when enumerating large amount of data,

  if possible avoid using InstancesOf and use ExecQuery Instead.

 

Browsing the CIM Schema

  Windows provides WMI tools like wbemtest.exe, see your documentation if it is installed.

 

WMI Tester (wbemtest.exe)

  is a general-purpose, graphical tool for interacting with the WMI infrastructure.

                 

  1. run wbemtest.exe

  2. Click Connect button to open Connect dialog.

  3. If Namespace value is root\default, Change the Namespace field's value to root\cimv2 and click the Connect

    dialog's Connect button to return to the main WMI Tester window.

  4. Click Enum Classes… to open the Superclass Info dialog.

  5. In the Superclass Info dialog, leave the Enter superclass name field blank, click the Recursive option, and

    click OK to enumerate all CIM classes defined in the root\cimv2 namespace.

  6. Scroll down the Query Result dialog until you reach the Win32 Class, and double-click the class name you

    want to open eg. Win32_Process

  7. Select the Hide System Properties check box to hide the system properties, remaining Win32_Process

    properties represent the information you can retrieve from the processes running on a local computer.

    The Object editor dialog reveals the definition and implementation details (properties and methods) of the

    selected class.

  8. Click Instances button to show the Instances available, eg: Win32_Process.Handle=”0”

 

  This is only a thin slice of what COM is all about Particularly WMI, for a start there’s Lot of libraries you can play with,

  like WIA(Windows Image Acquisition) , WMP (Windows Media Player) Library etc..

 

  NOTE:

  This tutorial is based on my knowledge on VBScript and Jscript, some part of the tutorial may or may not work

  on mIRC versions or OS version, just keep in mind that experimenting will help a lot in understanding how COM

  works with mIRC. hope you enjoyed and learned from this tutorial! Good Luck.

 

Up